package com.example.boot1;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

//资源类
class MyCache{
    //可见性，及时性
    private volatile Map<String,Object> map = new HashMap<>();
    //既保证了原子性，又保证了并发性
    private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void put(String key ,Object value){
        rwLock.writeLock().lock();
        try{
            System.out.println(Thread.currentThread().getName()+"\t 正在写入"+key);
            try{ TimeUnit.MILLISECONDS.sleep(300);} catch(Exception e){e.printStackTrace();}
            map.put(key,value);
            System.out.println(Thread.currentThread().getName()+"\t 写入完成");
            //结果
            /*
            1	 正在写入1
            1	 写入完成
            2	 正在写入2
            2	 写入完成
            3	 正在写入3
            3	 写入完成
            4	 正在写入4
            4	 写入完成
            5	 正在写入5
            5	 写入完成
            2	 正在读取
            3	 正在读取
            1	 正在读取
            4	 正在读取
            5	 正在读取
            2	 读取完成2
            1	 读取完成1
            4	 读取完成4
            5	 读取完成5
            3	 读取完成3
*/
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            rwLock.writeLock().unlock();
        }
// 不加锁的情况下写被分割，被打断
//执行结果
/*
2	 正在写入2
3	 正在写入3
5	 正在写入5
4	 正在写入4
1	 正在写入1
1	 正在读取
3	 正在读取
2	 正在读取
4	 正在读取
5	 正在读取
5	 写入完成
4	 写入完成
1	 写入完成
1	 读取完成null
5	 读取完成null
2	 写入完成
4	 读取完成null
2	 读取完成null
3	 读取完成null
3	 写入完成
 */
//        System.out.println(Thread.currentThread().getName()+"\t 正在写入"+key);
//        try{ TimeUnit.MILLISECONDS.sleep(300);} catch(Exception e){e.printStackTrace();}
//        map.put(key,value);
//        System.out.println(Thread.currentThread().getName()+"\t 写入完成");

    }

    public void get(String key){
        rwLock.readLock().lock();
        try{
            System.out.println(Thread.currentThread().getName()+"\t 正在读取");
            try{ TimeUnit.MILLISECONDS.sleep(300);} catch(Exception e){e.printStackTrace();}
            Object result  = map.get(key);
            System.out.println(Thread.currentThread().getName()+"\t 读取完成"+result);
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            rwLock.readLock().unlock();
        }
//        System.out.println(Thread.currentThread().getName()+"\t 正在读取");
//        try{ TimeUnit.MILLISECONDS.sleep(300);} catch(Exception e){e.printStackTrace();}
//        Object result  = map.get(key);
//        System.out.println(Thread.currentThread().getName()+"\t 读取完成"+result);

    }


}

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        //线程访问资源类
        MyCache myCache = new MyCache();

        //5个线程写
        for (int i = 1; i <= 5; i++) {
            final int tempInt = i;
            new Thread(() -> {
                myCache.put(tempInt +"",tempInt +"");
            }, String.valueOf(i)).start();

        }

        //5个线程读
        for (int i = 1; i <= 5; i++) {
            final int tempInt = i;
            new Thread(() -> {
                myCache.get(tempInt+"");
            }, String.valueOf(i)).start();

        }

    }
}
